#ifndef REAL_CUH
#define REAL_CUH

//Incluyo la clase Random para la generación de números aleatorios en CUDA
#include "../utils/Random.cu"

/****************** Representacion real ********************/

/******************* Declaracion de Funciones del Host *************************/
void representacionReal();
void traerImprimirReal(float* fitnessHost, float* fitnessDevice, int tamVectorFitnessFloat, float* poblacionHost, float* poblacionDevice, int tamVectorPoblacion, int iteracion);
void traerImprimirMejorIndividuoReal(float* mejorFitnessIndividuoGPU, float* mejorFitnessIndividuoGPUDevice, int tamVectorFitnessMejoresIndividuosGPU, float* mejorIndividuoGPU, float* mejorIndividuoGPUDevice, int tamVectorMejoresIndividuosGPU, int iteracion);

/******************* Declaracion de Funciones Global del Device ********************/
__global__ void inicializarPoblacionReal(float* poblacion, float* fitnessActualDevice, struct Random randomGPU, int cantCromosomasPoblacion, float* fitnessOrdenadoDevice);
__global__ void mainKernelReal(float* poblacionActualDevice, float* nuevaPoblacionDevice, float* fitnessActualDevice, float* nuevoFitnessDevice, int* poblacionActualAcambiarDevice, int* nuevaPoblacionAcambiarDevice, float* individuosAMigrarDevice, struct Random r, int generacionActual, float * individuoAMigrarGPUaCPUdevice, float* fitnessOrdenadoDevice, int* vectorIndicesFitnessOrdenado, int iteracion, float* mejorIndividuoGPUDevice, float* mejorFitnessIndividuoGPUDevice);

/******************* Declaracion de Funciones internas del Device *****************/
__device__ int obtenerMejorIndividuoReal(float* vectorFitness);
__device__ void obtenerPeorIndividuoReal(float* vectorFitness, int indices[2]);

__global__ void migracionRepresentacionReal(float* poblacionActualDevice, float* fitnessActualDevice, float* individuosAMigrarDevice, struct Random randomGPU, float* individuoAMigrarCPUaGPUdevice);
__global__ void obtenerMejoresIndividuosReal(float* poblacion, float* fitness, float* mejorIndividuoDevice, float* mejorFitnessIndividuoGPUDevice);
__device__ void individosAMigrarRepresentacionReal(float* nuevoFitnessDevice, float* nuevaPoblacionDevice, float* individuosAMigrarDevice, float * individuoAMigrarGPUaCPUdevice);

__device__ void asignarProbabilidadRuletaReal(float* fitnessActualDevice, float* probabilidadRuletaBinaria, float* fitnessTotalParaRuletaDevice, struct Random randomGPU);

__device__ int seleccionReal(float* vectorFitness, float* probabilidadRuletaDevice, struct Random randomGPU, int ejecutarFuncion, int* vectorIndicesFitnessOrdenado);
__device__ int seleccionPorTorneoReal(float* vectorFitness, struct Random randomGPU);
__device__ int seleccionPorRangoReal(int* vectorIndicesFitnessOrdenado, struct Random randomGPU);
__device__ int seleccionRuedaRuletaReal(float* probabilidadRuletaDevice, struct Random randomGPU);

__device__ void cruzamientoRepresentacionReal(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU, int ejecutarFuncion);
__device__ void cruzamientoAritmeticoIndividual(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);
__device__ void cruzamientoAritmeticoSimple(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);
__device__ void cruzamientoAritmeticoCompleto(float* poblacionActual, float* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, float probabilidad, struct Random randomGPU);

__device__ void mutacionReal(float* poblacion, float probabilidad, struct Random randomGPU, int ejecutarFuncion, int generacionActual);
__device__ void mutacionUniforme(float* poblacion, float probabilidad, struct Random randomGPU);
__device__ void mutacionNoUniforme(float* poblacion, float probabilidad, struct Random randomGPU, int generacionActual);

__device__ void asignarFitnessReal(float* poblacion, float* vectorFitness, float* fitnessOrdenadoDevice);

__device__ void reemplazoReal(float* poblacionActualDevice, float* nuevaPoblacionDevice, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActualDevice, float* nuevoFitnessDevice, int ejecutarFuncion);
__device__ void reemplazoElitistaReal(float* poblacionActual, float* nuevaPoblacion, int* poblacionActualAcambiar, int* nuevaPoblacionAcambiar, float * fitnessActual, float* nuevoFitness);

#endif
